package com.pomr.dao.base.impl;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.DetachedCriteria;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate5.HibernateCallback;
import org.springframework.orm.hibernate5.HibernateTemplate;
import org.springframework.orm.hibernate5.SessionFactoryUtils;
import org.springframework.stereotype.Repository;

import com.pomr.dao.base.BaseDao;
import com.pomr.util.page.Page;
@SuppressWarnings("unchecked")//去除警告信息
@Repository
public class BaseDaoImpl implements BaseDao {
	public HibernateTemplate getHibernateTemplate() {
		return hibernateTemplate;
	}

	public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
		this.hibernateTemplate = hibernateTemplate;
	}

	@Autowired
	private HibernateTemplate hibernateTemplate;
	
	@Override  
    public <T> boolean add(T entity) throws Exception  
    {  
        boolean bool = false;  
        try  
        {  
            Serializable ser = hibernateTemplate.save(entity);  
            if (ser != null)  
            {  
                bool = true;  
            }  
        }  
        catch (Exception e)  
        {  
            bool = false;  
            throw new RuntimeException(e);  
        }  
        return bool;  
    }  
  
    @Override  
    public <T> String addStringKey(T entity) throws Exception  
    {  
        String id = null;  
        try  
        {  
            id = (String) hibernateTemplate.save(entity);  
        }  
        catch (Exception e)  
        {  
            throw new RuntimeException(e);  
        }  
        return id;  
    }  
  
    @Override  
    public <T> Integer addNumKey(T entity) throws Exception  
    {  
        Integer id = null;  
        try  
        {  
            id = (Integer) hibernateTemplate.save(entity);  
        }  
        catch (Exception e)  
        {  
            throw new RuntimeException(e);  
        }  
        return id;  
    }  
  
    @Override  
    public int executeData(String hql) throws Exception  
    {  
        try  
        {  
            return hibernateTemplate.bulkUpdate(hql);  
        }  
        catch (Exception e)  
        {  
            throw new RuntimeException(e);  
        }  
    }  
  
    @Override  
    public <T> List<T> findByHql(String hql) throws Exception  
    {  
        List<T> list = null;  
        try  
        {  
            list = (List<T>) hibernateTemplate.find(hql);  
        }  
        catch (Exception e)  
        {  
            throw new RuntimeException(e);  
        }  
        return list;  
    }  
    
    @Override  
    public <T> List<T> findByHqlWithDate(String hql,Map<String, Date> map,int page) throws Exception  
    {  
        List<T> list = null;  
        try  
        {  
        	Query query= session().createQuery(hql);
        	for(Entry<String, Date> itr : map.entrySet()){
        		query.setDate(itr.getKey(), itr.getValue());
        	}
        	if(page<0){
        		list = (List<T>) query.list();
        	}else{
        		list = (List<T>) query.setFirstResult(0).setMaxResults(page).list();
        	}
            
        }  
        catch (Exception e)  
        {  
            throw new RuntimeException(e);  
        }  
        return list;  
    } 
    
    @Override  
    public <T> List<T> findByHqlNoCache(String hql) throws Exception  
    {  
        List<T> list = null;  
        try  
        {  
        	list = session().createQuery(hql).list();
        	System.out.println(list.size());
        }  
        catch (Exception e)  
        {  
            throw new RuntimeException(e);  
        }  
        return list;  
    }
    
    @Override  
    public <T> List<T> findByHqlNoCacheWithDate(String hql, Map<String, Date> map) throws Exception  
    {  
        List<T> list = null;  
        try  
        {  
        	Query query = session().createQuery(hql);
        	for(Entry<String, Date> itr : map.entrySet()){
        		query.setDate(itr.getKey(), itr.getValue());
        	}
        	list = (List<T>) query.list();
        }  
        catch (Exception e)  
        {  
            throw new RuntimeException(e);  
        }  
        return list;  
    }
  
    @Override  
    public int executeBySql(String sql) throws Exception  
    {  
        try  
        {  
            return session().createSQLQuery(sql).executeUpdate();  
        }  
        catch (Exception e)  
        {  
            throw new RuntimeException(e);  
        }  
    }  
  
    @Override  
    public <T> List<T> findBySql(String sql, Class y) throws Exception
    {  
        try  
        {  
            return session().createSQLQuery(sql).addEntity(y).list();  
        }  
        catch (Exception e)  
        {  
            throw new RuntimeException(e);  
        }  
    }  
  
    @Override  
    public <T> boolean editEntity(T entity) throws Exception  
    {  
        boolean bool = false;  
        try  
        {  
        	hibernateTemplate.update(entity);  
            bool = true;  
        }  
        catch (Exception e)  
        {  
            bool = false;  
            throw new RuntimeException(e);  
        }  
        return bool;  
    }  
  
    @Override  
    public boolean editHql(String hql) throws Exception  
    {  
        boolean bool = false;  
        try  
        {  
            int num = hibernateTemplate.bulkUpdate(hql);  
            bool = num > 0 ? true : false;  
        }  
        catch (Exception e)  
        {  
            bool = false;  
            throw new RuntimeException(e);  
        }  
        return bool;  
    }

    @Override
    public boolean editHql(String hql, Object[] objs) throws Exception
    {
        boolean bool = false;
        try
        {
            int num = hibernateTemplate.bulkUpdate(hql, objs);
            bool = num > 0 ? true : false;
        }
        catch (Exception e)
        {
            bool = false;
            throw new RuntimeException(e);
        }
        return bool;
    }

    @Override  
    public int editNumHql(String hql) throws Exception  
    {  
        int count = 0;  
        try  
        {  
            count = hibernateTemplate.bulkUpdate(hql);  
        }  
        catch (Exception e)  
        {  
            count = 0;  
            throw new RuntimeException(e);  
        }  
        return count;  
    }  
  
    @Override  
    public <T> boolean removeEntity(T entity) throws Exception  
    {  
        boolean bool = false;  
        try  
        {  
        	hibernateTemplate.delete(entity);  
        	session().flush();
            bool = true;  
        }  
        catch (Exception e)  
        {  
            bool = false;  
            throw new RuntimeException(e);  
        }  
        return bool;  
    }  
  
    @Override  
    public <T> T getById(Class<T> clazz, int id) throws Exception  
    {  
        T t = null;  
        try  
        {  
            t = (T) hibernateTemplate.get(clazz, id);  
        }  
        catch (Exception e)  
        {  
            throw new RuntimeException(e);  
        }  
        return t;  
    }  
  
    @Override  
    public <T> T getById(Class<T> clazz, String id) throws Exception  
    {  
        T t = null;  
        try  
        {  
            t = (T) hibernateTemplate.get(clazz, id);  
        }  
        catch (Exception e)  
        {  
            throw new RuntimeException(e);  
        }  
        return t;  
    }  
  
    @Override  
    public <T> T getById(Class<T> clazz, Serializable id) throws Exception  
    {  
        T t = null;  
        try  
        {  
            t = (T) hibernateTemplate.get(clazz, id);  
        }  
        catch (Exception e)  
        {  
            throw new RuntimeException(e);  
        }  
        return t;  
    }  
  
    @Override  
    public <T> T getByHql(String hql) throws Exception  
    {  
        T t = null;  
        try  
        {  
            t = (T) session().createQuery(hql).setMaxResults(1).uniqueResult();  
        }  
        catch (Exception e)  
        {  
            throw new RuntimeException(e);  
        }  
        return t;  
    }  
  
    @Override  
    public <T> List<T> getList(String hql) throws Exception  
    {  
        List<T> list = null;  
        try  
        {  
            list = (List<T>) hibernateTemplate.find(hql);  
        }  
        catch (Exception e)  
        {  
            throw new RuntimeException(e);  
        }  
        return list;  
    }  
  
    @Override  
    public boolean remove(String hql) throws Exception  
    {  
        boolean bool = false;  
        try  
        {  
            bool = this.executeBySql(hql) > 0 ? true : false;  
        }  
        catch (Exception e)  
        {  
            bool = false;  
            throw new RuntimeException(e);  
        }  
        return bool;  
    }  
     
  
    @Override  
    public <T> List<T> getList(Class<T> clazz) throws Exception  
    {  
        List<T> list = null;  
        try  
        {  
            list = (List<T>) hibernateTemplate.findByCriteria(DetachedCriteria.forClass(clazz));  
        }  
        catch (Exception e)  
        {  
            throw new RuntimeException(e);  
        }  
        return list;  
    }  
  
    @Override  
    public <T> List<T> getList(String hql, Object[] obj) throws Exception  
    {  
        List<T> list = null;  
        try  
        {  
            list = (List<T>) hibernateTemplate.find(hql, obj);  
        }  
        catch (Exception e)  
        {  
            throw new RuntimeException(e);  
        }  
        return list;  
    }  
  
    @Override  
    public List<?> showPage(String queryHql, String queryCountHql, int firstResult, int maxResult) throws Exception  
    {  
        List<Object> list = new ArrayList<Object>();  
        try  
        {  
            Session session = session();  
            list.add(session.createQuery(queryHql).setFirstResult(firstResult).setMaxResults(maxResult).list());  
            list.add(session.createQuery(queryCountHql).setFirstResult(firstResult).uniqueResult());  
        }  
        catch (Exception e)  
        {  
            throw new RuntimeException(e);  
        }  
        return list;  
    }  
  
    @Override  
    public <T> Page<T> showPage(String queryHql, String queryCountHql, Page<T> page) throws Exception  
    {  
        try  
        {  
            Session session = session();
            System.out.println(System.currentTimeMillis());
            page.setRows((T) session.createQuery(queryHql).setFirstResult(page.getStartData())  
                    .setMaxResults(page.getPageSize()).list());
            System.out.println(System.currentTimeMillis());
            page.setTotal(Integer.parseInt(session.createQuery(queryCountHql).setMaxResults(1).uniqueResult()  
                    .toString()));
            System.out.println(System.currentTimeMillis());
        }  
        catch (Exception e)  
        {  
            throw new RuntimeException(e);  
        }  
        return page;  
    }  
    
    @Override  
    public <T> Page<T> showPageParam(String queryHql, String queryCountHql, Page<T> page, Map<String, Object> params) throws Exception  
    {  
        try  
        {  
            Session session = session(); 
            Query query = null;
            query = session.createQuery(queryHql);
            for(Entry<String, Object> param:params.entrySet()){
            	query.setParameter(param.getKey(), param.getValue());
            }
            page.setRows((T)query.setFirstResult(page.getStartData())  
                    .setMaxResults(page.getPageSize()).list());
            query = null;
            query = session.createQuery(queryCountHql);
            for(Entry<String, Object> param:params.entrySet()){
            	query.setParameter(param.getKey(), param.getValue());
            }
            page.setTotal(Integer.parseInt(query.setMaxResults(1).uniqueResult()  
                    .toString()));  
        }  
        catch (Exception e)  
        {  
            throw new RuntimeException(e);  
        }  
        return page;  
    }
  
    @Override  
    public List<?> showPage(String queryHql, DetachedCriteria criteria, int firstResult, int maxResult)  
            throws Exception  
    {  
        List<Object> list = new ArrayList<Object>();  
        try  
        {  
            Session session = session();  
            list.add(hibernateTemplate.findByCriteria(criteria, firstResult, maxResult));  
            list.add(session.createQuery(queryHql).setMaxResults(1).uniqueResult());  
        }  
        catch (Exception e)  
        {  
            throw new RuntimeException(e);  
        }  
        return list;  
    }  
  
    @Override  
    public <T> List<T> showPage(String queryHql, DetachedCriteria criteria, Page<T> page) throws Exception  
    {  
        try  
        {  
            Session session = session();  
            page.setRows((T) hibernateTemplate.findByCriteria(criteria, page.getStartData(),  
                    page.getPageSize()));  
            page.setTotal(Integer.parseInt(session.createQuery(queryHql).setMaxResults(1).uniqueResult()  
                    .toString()));  
        }  
        catch (Exception e)  
        {  
            throw new RuntimeException(e);  
        }  
        return (List<T>) page.getRows();  
    }  
  
    @Override  
    public <T> List<T> find(DetachedCriteria criteria) throws Exception  
    {  
        List<T> list = null;  
        try  
        {  
            list=(List<T>) hibernateTemplate.findByCriteria(criteria);  
        }  
        catch (Exception e)  
        {  
            throw new RuntimeException(e);  
        }  
        return list;  
    }  
  
    @Override  
    public Session session()  
    {  
        return hibernateTemplate.getSessionFactory().openSession();
    }

	@Override
	public boolean updateorsave(String preSql, List<List> list, int paramNum, int batchNum) {
		Session session = null;
		try{
		session = session();
		Connection conn = session.disconnect();
		PreparedStatement stmt = conn.prepareStatement(preSql);
		List nlist = null;
		for(int i = 0; i<list.size(); i++) {
			nlist = list.get(i);
		    for(int j=1; j<=paramNum;j++){
		    	stmt.setObject(j, nlist.get(j-1));
		    }
		    stmt.addBatch();
		    if (i % batchNum == 0) {
		        stmt.executeBatch();
		        conn.commit();
		    }
		}
		stmt.executeBatch();
		conn.commit();

		}catch (Exception e) {
			e.printStackTrace();
			return false;
		}finally {
			// 关闭session
			session.close();
		}
		return true;
	}

	@Override
	public <T> boolean saveOrUpdateEntity(T entity) throws Exception {
		boolean bool = false;  
        try  
        {  
        	hibernateTemplate.saveOrUpdate(entity); 
            bool = true;  
        }  
        catch (Exception e)  
        {  
            bool = false;  
            throw new RuntimeException(e);  
        }  
        return bool; 
	}

    @Override
    public <T> boolean batchSaveOrUpdate(final List<T> list) throws Exception {
        return (boolean) getHibernateTemplate().execute(new HibernateCallback<Object>() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                for (int i = 0; i < list.size(); ++i) {
                    Integer id = (Integer) session.save(list.get(i));
                    if(id <= 0){
                        return false;
                    }
                }
                session.flush();
                session.clear();
                return true;
            }
        });
    }
}
